package com.tbit.main.service.impl;

import com.tbit.main.constant.BrandRemoteConfigConstant;
import com.tbit.main.dao.core.BmsBatteryDao;
import com.tbit.main.exception.BaseException;
import com.tbit.main.pojo.*;
import com.tbit.main.service.*;
import com.tbit.main.util.DateTimeUtil;
import com.tbit.main.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author LMY
 * @create 2022-07-14 17:34
 */
@Service("bmsBatteryService")
public class BmsBatteryServiceImpl implements BmsBatteryService {

    @Autowired
    private BmsBatteryDao bmsBatteryDao;
    @Autowired
    private DataService dataService;
    @Autowired
    private BatteryService batteryService;
    @Autowired
    private BrandRemoteConfigService brandRemoteConfigService;
    @Autowired
    private PowerChangeLogExpandService powerChangeLogExpandService;


    @Override
    public List<BmsBattery> getBattery(BmsStat bmsStat) {

        BrandRemoteConfig brandRemoteConfig = brandRemoteConfigService.getByAccountIdAndType(bmsStat.getAccountId(), BrandRemoteConfigConstant.BMS);

        List<BmsBattery> bmsBatteries = new LinkedList<>();

        if (brandRemoteConfig != null) {
            BmsConfig bmsConfigByStr = new BmsConfig().getBmsConfigByStr(brandRemoteConfig.getParamKV());


            bmsBatteries = bmsBatteryDao.getBattery(bmsStat);

            if (bmsBatteries != null && bmsBatteries.size() > 0) {
                for (BmsBattery bmsBattery : bmsBatteries) {
                    bmsBattery.setBatteryModelName(dataService.getByIdBatteryModelChart(dataService.getModelId(bmsBattery.getBatteryNO())).getBatteryModel());
                    if (bmsBattery.getBatch() != null) {
                        bmsBattery.setBatchName(dataService.getBmsBatch(bmsBattery.getBatch()).getBatchName());
                    }
                    bmsBattery.setUseDay(DateTimeUtil.getDayCountByRange(bmsBattery.getFirstTime(), DateTimeUtil.getNowTime()));
                    bmsBattery.setStandardMileage(dataService.getByIdBatteryModelChart(dataService.getModelId(bmsBattery.getBatteryNO())).getMaxMileage());
                    if (bmsBattery.getHealth() > bmsConfigByStr.getLifePoorHealth()) {
                        bmsBattery.setHealthGrade(1);
                    } else if (bmsConfigByStr.getLifePoorHealth() >= bmsBattery.getHealth() && bmsBattery.getHealth() > bmsConfigByStr.getAdviceRecycleHealth()) {
                        bmsBattery.setHealthGrade(2);
                    } else if (bmsConfigByStr.getAdviceRecycleHealth() >= bmsBattery.getHealth() && bmsBattery.getHealth() > bmsConfigByStr.getScrapHealth()) {
                        bmsBattery.setHealthGrade(3);
                    } else if (bmsConfigByStr.getScrapHealth() >= bmsBattery.getHealth()) {
                        bmsBattery.setHealthGrade(4);
                    }
                }
            }
        }


        return bmsBatteries;
    }

    @Override
    public BmsBatteryHealthAnalyse getHealth(BmsStat bmsStat) {

        List<BmsBatteryHealthMsg> bmsBatteries = bmsBatteryDao.getBatteryMsg(bmsStat);

        if (bmsBatteries != null && bmsBatteries.size() > 0) {
            BrandRemoteConfig brandRemoteConfig = brandRemoteConfigService.getByAccountIdAndType(bmsStat.getAccountId(), BrandRemoteConfigConstant.BMS);

            BmsConfig bmsConfigByStr = new BmsConfig().getBmsConfigByStr(brandRemoteConfig.getParamKV());

            return bmsBatteryHealthAnalyze(bmsBatteries, bmsConfigByStr.getLifePoorHealth(), bmsConfigByStr.getAdviceRecycleHealth(), bmsConfigByStr.getScrapHealth());
        } else {
            return null;
        }
    }

    @Override
    public void insert(Integer accountId, String batteryNO, Integer batch) {

        /**判断授权数量*/
        BrandRemoteConfig brandRemoteConfig = brandRemoteConfigService.getByAccountIdAndType(accountId, BrandRemoteConfigConstant.BMS);

        if (brandRemoteConfig == null) {
            throw new BaseException("bms.config.notExit");
        }
        BmsConfig bmsConfigByStr = new BmsConfig().getBmsConfigByStr(brandRemoteConfig.getParamKV());
        BmsStat bmsStat = new BmsStat();
        bmsStat.setAccountId(accountId);
        List<BmsBattery> bmsBatteries = bmsBatteryDao.getBattery(bmsStat);
        if (bmsBatteries != null && bmsBatteries.size() >= bmsConfigByStr.getCount()) {
            throw new BaseException("bms.count");
        }

        bmsStat.setBatteryNO(batteryNO);
        List<BmsBattery> bmsBatteries1 = bmsBatteryDao.getBattery(bmsStat);
        if (bmsBatteries1 != null && bmsBatteries1.size() > 0) throw new BaseException("Battery.batteryNO.exist");

        Battery battery = batteryService.getByNO(batteryNO);

        /**添加*/
        BmsBattery bmsBattery = new BmsBattery();
        bmsBattery.setAccountId(dataService.getParentId(battery.getAccountId()));
        bmsBattery.setAdAccountId(battery.getAccountId());
        bmsBattery.setBatteryNO(batteryNO);
        if (batch == null) {
            batch = 0;
        }
        bmsBattery.setBatch(batch);
        bmsBattery.setAddTime(DateTimeUtil.getNowTime());
        bmsBattery.setFirstTime(battery.getAddTime());
        bmsBattery.setUseCount(battery.getUseCount());
        bmsBattery.setFinallyMileage(0.00);

        List<PowerChangeLogExpand> powerChangeLogExpands = powerChangeLogExpandService.getNO(batteryNO);
        List<Double> mileages = powerChangeLogExpands.stream().map(PowerChangeLogExpand::getMileage).collect(Collectors.toList());
        mileages = mileages.stream().filter(Objects::nonNull).collect(Collectors.toList());
        Double mileage = mileages.stream().mapToDouble(s -> s).sum();
        bmsBattery.setSumMileage(mileage);
        bmsBattery.setAbnormalType(0);
        bmsBatteryDao.insert(bmsBattery);
    }

    @Override
    public void insertBatch(Integer accountId, List<String> batteryNOs, Integer batch) {

        /**判断授权数量*/
        BrandRemoteConfig brandRemoteConfig = brandRemoteConfigService.getByAccountIdAndType(accountId, BrandRemoteConfigConstant.BMS);
        if (brandRemoteConfig == null) {
            throw new BaseException("bms.config.notExit");
        }
        BmsConfig bmsConfigByStr = new BmsConfig().getBmsConfigByStr(brandRemoteConfig.getParamKV());
        BmsStat bmsStat = new BmsStat();
        bmsStat.setAccountId(accountId);
        List<BmsBattery> bmsBatteries = bmsBatteryDao.getBattery(bmsStat);
        if (bmsBatteries != null && bmsBatteries.size() >= bmsConfigByStr.getCount()) {
            throw new BaseException("bms.count");
        }

        List<BmsBattery> bmsBatteries1 = bmsBatteryDao.getBatteryNOs(StringUtil.getStringListString(batteryNOs));
        if (bmsBatteries1 != null && bmsBatteries1.size() > 0) {
            throw new BaseException("Battery.batteryNO.exist");
        }

        /**判断电池批次区域*/
        List<Battery> batteries = batteryService.getBatteryNOs(batteryNOs);

        /**添加*/
        List<BmsBattery> batteryBatch = new LinkedList<>();
        if (batch == null) {
            batch = 0;
        }

        List<PowerChangeLogExpand> powerChangeLogExpands = powerChangeLogExpandService.getNO(StringUtil.getStringListString(batteryNOs));
        Map<String, List<PowerChangeLogExpand>> map = new HashMap<>();
        for (PowerChangeLogExpand powerChangeLogExpand : powerChangeLogExpands) {
            if (map.containsKey(powerChangeLogExpand.getBatteryNONew())) {
                map.get(powerChangeLogExpand.getBatteryNONew()).add(powerChangeLogExpand);
            } else {
                List<PowerChangeLogExpand> powerChangeLogExpands1 = new LinkedList<>();
                powerChangeLogExpands1.add(powerChangeLogExpand);
                map.put(powerChangeLogExpand.getBatteryNONew(), powerChangeLogExpands1);
            }
        }
        Map<String, Double> mileageMap = new HashMap<>();
        for (String NO : map.keySet()) {
            List<Double> mileages = map.get(NO).stream().map(PowerChangeLogExpand::getMileage).collect(Collectors.toList());
            mileages = mileages.stream().filter(e -> e != null).collect(Collectors.toList());
            Double mileage = mileages.stream().mapToDouble(s -> s).sum();
            mileageMap.put(NO, mileage);
        }

        for (Battery battery : batteries) {
            BmsBattery bmsBattery = new BmsBattery();
            bmsBattery.setAccountId(dataService.getParentId(battery.getAccountId()));
            bmsBattery.setAdAccountId(battery.getAccountId());
            bmsBattery.setBatteryNO(battery.getBatteryNO());
            bmsBattery.setBatch(batch);
            bmsBattery.setAddTime(DateTimeUtil.getNowTime());
            bmsBattery.setFirstTime(battery.getAddTime());
            bmsBattery.setUseCount(battery.getUseCount());
            if (mileageMap.containsKey(battery.getBatteryNO())) {
                bmsBattery.setSumMileage(mileageMap.get(battery.getBatteryNO()));
            } else {
                bmsBattery.setSumMileage(0.00);
            }
            bmsBattery.setFinallyMileage(0.00);
            bmsBattery.setAbnormalType(0);
            batteryBatch.add(bmsBattery);
        }

        bmsBatteryDao.insertBatch(batteryBatch);
    }

    @Override
    public List<BmsBattery> getBatch(Integer batch) {
        return bmsBatteryDao.getBatch(batch);
    }

    @Override
    public void updateHandle(String batteryNOs) {
        bmsBatteryDao.updateHandle(batteryNOs);
    }

    @Override
    public void delete(String batteryNO) {
        bmsBatteryDao.delete(batteryNO);
    }

    @Override
    public void auth(List<String> batteryNOs, Integer adAccountId) {
        List<Battery> batteries = batteryService.getBatteryNOs(batteryNOs);
        if (batteryNOs.size() != batteries.size()) {
            throw new BaseException("Battery.battery.notNull");
        }
        List<Integer> accountId = batteries.stream().map(Battery::getAccountId).collect(Collectors.toList());
        accountId = accountId.stream().distinct().collect(Collectors.toList());
        if (accountId.size() != 1) {
            throw new BaseException("bms.accountId.adAccountId");
        } else {
            if (!accountId.get(0).equals(adAccountId)) {
                throw new BaseException("bms.accountId.adAccountId");
            }

        }
    }


    /**
     * 云bms电池健康度分析
     *
     * @param bmsBatteryHealthMsgList 云bms电池健康度信息
     * @param lifePoorHealth          续航差健康度
     * @param adviceRecycleHealth     建议回收健康度
     * @param scrapHealth             报废健康度
     * @return
     */
    public BmsBatteryHealthAnalyse bmsBatteryHealthAnalyze(List<BmsBatteryHealthMsg> bmsBatteryHealthMsgList, Integer lifePoorHealth, Integer adviceRecycleHealth, Integer scrapHealth) {

        //初始化云bms电池健康等级图表
        BmsBatteryHealthChart bmsBatteryHealthChart = new BmsBatteryHealthChart();
        //初始化云bms电池健康度曲线(按批次划分)
        List<BmsBatteryHealthCurve> bmsBatteryHealthCurves = new ArrayList<>();
        //根据批次号分组
        Map<Integer, List<BmsBatteryHealthMsg>> bmsBatteryHealthMsgGroupByBatch = bmsBatteryHealthMsgList.stream().collect(Collectors.groupingBy(BmsBatteryHealthMsg::getBatch));
        for (Map.Entry<Integer, List<BmsBatteryHealthMsg>> entry : bmsBatteryHealthMsgGroupByBatch.entrySet()) {
            List<BmsBatteryHealthMsg> value = entry.getValue();
            //一个批次一个对象
            BmsBatteryHealthCurve bmsBatteryHealthCurve = new BmsBatteryHealthCurve()
                    .setBatch(entry.getKey())
                    .setBatchName(value.get(0).getBatchName())
                    .setTotal(value.size());
            for (BmsBatteryHealthMsg bmsBatteryHealthMsg : value) {
                //电池健康度
                Integer health = bmsBatteryHealthMsg.getHealth();
                if (health > lifePoorHealth) {
                    //正常
                    bmsBatteryHealthChart.incrNormalCount();
                } else if (health > adviceRecycleHealth) {
                    //续航差
                    bmsBatteryHealthChart.incrLifePoorCount();
                } else if (health > scrapHealth) {
                    //建议回收
                    bmsBatteryHealthChart.incrAdviceRecycleCount();
                } else {
                    //报废
                    bmsBatteryHealthChart.incrScrapCount();
                }
                //电池健康度范围统计
                bmsBatteryHealthCurve.statistics(health);
            }
            //电池健康度范围计算
            bmsBatteryHealthCurve.compute();
            bmsBatteryHealthCurves.add(bmsBatteryHealthCurve);
        }
        return new BmsBatteryHealthAnalyse(bmsBatteryHealthCurves, bmsBatteryHealthChart);
    }
}
